package com.hwd.gmall.product.service.impl;

import com.hwd.gmall.common.constant.CacheConst;
import com.hwd.gmall.product.service.TestService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 测试redis
 *
 * @author 黄伟东/Victor
 * @date 2022/4/23 10:43
 */
@Service
public class TestServiceImpl implements TestService {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private RedissonClient redissonClient;

    /**
     * 往redis中设置值操作
     */
    @Override
    public void setValue() {
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        // 进行 setnx操作，返回true的才能进行++操作，否则重试
        Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid, 10, TimeUnit.SECONDS);
        if (lock) {
            // 从redis中获取一个key=java1025的值
            Integer i = (Integer) redisTemplate.opsForValue().get("java1025");
            // 判断这个key是否存在，存在则+1操作
            if (i != null) {
                i++;
                // 把值更新到redis中
                redisTemplate.opsForValue().set("java1025", i);
            }

            // 释放锁流程: 取锁的值--->判断--->删除，不可取

            DefaultRedisScript<Long> script = new DefaultRedisScript<>();
            script.setScriptText("if redis.call('get', KEYS[1]) == ARGV[1] " +
                    "then return redis.call('del', KEYS[1]) " +
                    "else return 0 end ");
            script.setResultType(Long.class);
            //释放锁流程(一步完成):lua
            redisTemplate.execute(script, Collections.singletonList("lock"), uuid);

        } else {
            try {
                // 重试
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 递归调用自己
            setValue();
        }
    }

    /**
     * 往redis中设置值操作
     */
    @Override
    public void setValueRedisson() {
        // 获取锁
        RLock lock = redissonClient.getLock("lock");
        try {
            // 加锁，加锁成功的可以进行+1操作
            if (lock.tryLock(CacheConst.LOCK_WAIT_TIME, CacheConst.LOCK_LEASE_TIME, TimeUnit.SECONDS)) {
                try {
                    // 从redis中获取一个key=java1025的值
                    Integer i = (Integer) redisTemplate.opsForValue().get("java1025");
                    // 判断这个key是否存在，存在则+1操作
                    if (i != null) {
                        i++;
                        // 把值更新到redis中
                        redisTemplate.opsForValue().set("java1025", i);
                    }
                } catch (Exception e) {
                    System.out.println("加锁成功的,但是逻辑处理的时候出异常的!");
                } finally {
                    lock.unlock();
                }
            }

        } catch (InterruptedException e) {
            System.out.println("加锁出现异常,加锁失败的!!");
        }
    }
}
